from operator import and_

from flask import Blueprint, jsonify
from flask_restful import Api, Resource, reqparse

from common.utils.jwt_utils import _generate_token
from common.utils.redis_client import RedisOper

user_bp = Blueprint('ubp', __name__, url_prefix='/users')
api = Api(user_bp)

from models.user import *
from werkzeug.security import generate_password_hash
from models import db
import random

from tasks.sms.task import sms_code


# 注册
class UserRegister(Resource):
    def post(self):
        parser = reqparse.RequestParser()
        parser.add_argument('username')
        parser.add_argument('password')
        parser.add_argument('nick_name')
        parser.add_argument('mobile')
        parser.add_argument('confirmpassword')
        args = parser.parse_args()
        uname = args.get('username')
        pwd = args.get('password')
        nick_name = args.get('nick_name')
        mobile = args.get('mobile')
        confirm_pwd = args.get('confirmpassword')
        print("qqq", confirm_pwd)
        print('??', pwd, "...", confirm_pwd)
        if len(uname) > 32:
            return jsonify({'message': '账号太长', 'code': 400})
        if pwd != confirm_pwd:
            return jsonify({'message': '两次密码不一样', 'code': 400})
        user = UserModel.query.filter_by(mobile=mobile).count()
        if user >= 1:
            return jsonify({'message': '此手机号已存在', 'code': 400})
        # 存入数据库
        hash_pwd = generate_password_hash(pwd)
        try:
            user = UserModel(mobile=mobile, account=uname, password=hash_pwd, uname=nick_name)
            db.session.add(user)
            db.session.commit()
            return jsonify(message='注册成功', code=200)
        except Exception as e:
            print('register error %s' % e)
            return jsonify(message='注册失败', code=500)


# 发送短信验证码
class SendSmsCode(Resource):
    def post(self):
        parser = reqparse.RequestParser()
        parser.add_argument('mobile')
        args = parser.parse_args()
        mobile = args.get('mobile')
        code = random.randint(10000, 99999)
        print("code", code)
        rest = sms_code.delay(mobile, code)
        print("rest>>>", rest)
        if rest:
            # 发送成功,把短信验证码写入到redis
            rds = RedisOper()
            print(rds)
            rds.set_v(mobile, 60, code)
            return jsonify(message="短信验证码发送成功", code=200)
        else:
            return jsonify(message='短线验证码发送失败', code=500)


from datetime import timedelta


# 登录
class UserLogin(Resource):
    def post(self):
        """登录"""
        parser = reqparse.RequestParser()
        parser.add_argument('mobile')
        parser.add_argument('code')
        args = parser.parse_args()
        mobile = args.get('mobile')
        sms_code = args.get('code')
        print("sms_code", sms_code)
        if not all([mobile, sms_code]):
            return jsonify(message='登录信息不完整', code=400)
        rds = RedisOper()
        origin_sms_code = rds.get_v(mobile)
        if not origin_sms_code:
            return jsonify(message='验证码已过期', code=500)
        if sms_code != origin_sms_code.decode('utf-8'):
            return jsonify(message='验证码错误', code=400)
        # 登录成功,生成token
        try:
            user = UserModel.query.filter_by(mobile=mobile).first()
            print('user>>', user)
            data = {
                'user': user.account,
                'id': user.uid
            }
            # 登录生成的token中包含刷新token
            token, refresh_token = _generate_token(data, is_refresh=False)
            print('token>>', token, refresh_token)
            if token:
                data_ = {
                    'user_id': user.uid,
                    'token': token,
                    'refresh_token': refresh_token
                }
                print("data", data_)
                return jsonify(message='登录成功', code=200, data=data_)
            else:
                return jsonify(message='token生成失败', code=500)

        except Exception as e:
            print('获取用户错误', e)
            return jsonify(message='此手机号未注册', code=400)


# 获取用户
from common.model_fields.user import user_fields
from flask_restful import marshal
from common.utils.login_utils import login_required


# 修改密码
class UpdatePwd(Resource):
    @login_required
    def put(self, id):
        parser = reqparse.RequestParser()
        parser.add_argument('password')
        args = parser.parse_args()
        new_pwd = args.get('password')
        try:
            UserModel.query.filter_by(uid=id).update({'password': new_pwd})
            db.session.commit()
        except Exception as e:
            print("更新失败", e)
        return jsonify(message='更新成功', code=200)


from flask import g
from common.model_fields.user import channels_fields


# 我的频道
class UserChannelResource(Resource):
    @login_required
    def get(self):
        """
        获取用户关注的频道
        1.用户必须先登录
        2.根据登录的用户id，查询关注的频道
        """
        uid = g.user_id
        if uid:
            user = UserModel.query.filter_by(uid=uid).first()
            # 根据登录的用户id，查询关注的频道
            channels = marshal(user.channels, channels_fields)
            print(channels)
            return channels


# 取消关注
class CancelUserChannelResource(Resource):

    @login_required
    def get(self, id):
        """
        取消关注的频道
        获取当前用户的所有关注频道信息, 然后从里面取消关注的删除
        """
        uid = g.user_id
        if uid:
            user = UserModel.query.filter_by(uid=uid).first()
            # 根据登录的用户id, 查询关注的频道
            UserChannel.query.filter(and_(UserChannel.uid == user.uid, UserChannel.cid == id)).delete()
            db.session.commit()

        return jsonify(message='取消成功', code=200)


from common.utils.user_cache import UserCache


class UserInfo(Resource):
    @login_required
    def get(self, id):
        user_id = id
        user = UserCache(user_id)
        data_ = user.get()
        print('data', data_)
        return data_

    @login_required
    def patch(self, id):
        """修改用户信息"""
        parser = reqparse.RequestParser()
        parser.add_argument('name')
        parser.add_argument('password')
        parser.add_argument('gender')
        parser.add_argument('img')
        args = parser.parse_args()
        nick_name = args.get('name')
        pwd = args.get('password')
        gender = args.get('gender')
        img = args.get('img')
        if img:
            # 修改昵称
            UserModel.query.filter_by(uid=g.user_id).update({'profile_photo': img})
            db.session.commit()
            return jsonify(message="修改头像成功", code=200)
        if nick_name:
            # 修改昵称
            UserModel.query.filter_by(uid=g.user_id).update({'uname': nick_name})
            db.session.commit()
            return jsonify(message="修改成功", code=200)
        if pwd:
            has_pwd = generate_password_hash(pwd)
            UserModel.query.filter_by(uid=g.user_id).update({'password': has_pwd})
            db.session.commit()
            return jsonify(message='修改成功', code=200)
        if gender:
            UserModel.query.filter_by(uid=g.user_id).update({'gender': gender})
            db.session.commit()
            return jsonify(message="修改成功", code=200)


# 上传七牛云
from common.utils.qiniu import qiniu_token


class QiniuTokenResource(Resource):
    @login_required
    def get(self):
        """生成七牛云上传的token"""
        token = qiniu_token()
        return jsonify(message='生成ok', code=200, data={'token': token})


api.add_resource(SendSmsCode, '/send_sms_code')
api.add_resource(UserRegister, '/register')
api.add_resource(UserLogin, '/login')
api.add_resource(UserInfo, '/userinfo/<int:id>')
api.add_resource(UpdatePwd, '/user/<int:id>')
api.add_resource(UserChannelResource, '/user/channels')
api.add_resource(CancelUserChannelResource, '/user_channel/<int:id>')
api.add_resource(QiniuTokenResource, '/qiniu_token')
